package com.bankcard.bininfo.model;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

// This class is used to store issuer information for different banks and financial institutions.
// WARNING: ALL THE HARDCODED ISSUERS ARE AI GENERATED, MAKE SURE TO VALIDATE THEM BEFORE USING IN PRODUCTION
public final class Issuers {
    private static final Map<String, IssuerInfo> ISSUERS = new ConcurrentHashMap<>();

    public static final IssuerInfo ANZ = new IssuerInfo("Australia and New Zealand Banking Group", "ANZ", "https://www.anz.com", "13 13 14", Countries.AUSTRALIA);
    public static final IssuerInfo NAB = new IssuerInfo("National Australia Bank", "NAB", "https://www.nab.com.au", "13 22 65", Countries.AUSTRALIA);
    public static final IssuerInfo ITAU = new IssuerInfo("Itaú Unibanco", "ITAU", "https://www.itau.com.br", "0800 728 0728", Countries.BRAZIL);
    public static final IssuerInfo RBC = new IssuerInfo("Royal Bank of Canada", "RBC", "https://www.rbc.com", "800-769-2511", Countries.CANADA);
    public static final IssuerInfo SCOTIABANK = new IssuerInfo("Scotiabank", "BNS", "https://www.scotiabank.com", "800-472-6842", Countries.CANADA);
    public static final IssuerInfo BNP = new IssuerInfo("BNP Paribas", "BNP", "https://www.bnpparibas.com", "+33 1 40 14 45 46", Countries.FRANCE);
    public static final IssuerInfo CREDIT_AGRICOLE = new IssuerInfo("Crédit Agricole", "CA", "https://www.credit-agricole.com", "+33 1 43 23 52 02", Countries.FRANCE);
    public static final IssuerInfo SOCIETE_GENERALE = new IssuerInfo("Société Générale", "SG", "https://www.societegenerale.com", "+33 1 42 14 20 00", Countries.FRANCE);
    public static final IssuerInfo DEUTSCHE = new IssuerInfo("Deutsche Bank", "DB", "https://www.db.com", "+49 69 910-00", Countries.GERMANY);
    public static final IssuerInfo HSBC_HK = new IssuerInfo("HSBC Hong Kong", "HSBC", "https://www.hsbc.com.hk", "2233 3000", Countries.HONG_KONG);
    public static final IssuerInfo CTBC = new IssuerInfo("CTBC Bank", "CTBC", "https://www.ctbcbank.com", "0800-024-365", Countries.TAIWAN);
    public static final IssuerInfo UNICREDIT = new IssuerInfo("UniCredit", "UCG", "https://www.unicreditgroup.eu", "+39 02 8862 1", Countries.ITALY);
    public static final IssuerInfo MUFG = new IssuerInfo("Mitsubishi UFJ Financial Group", "MUFG", "https://www.mufg.jp", "0120-860-777", Countries.JAPAN);
    public static final IssuerInfo ING = new IssuerInfo("ING Group", "ING", "https://www.ing.com", "+31 20 563 9111", Countries.NETHERLANDS);
    public static final IssuerInfo SBERBANK = new IssuerInfo("Sberbank", "SBER", "https://www.sberbank.ru", "+7 495 500-55-50", Countries.RUSSIA);
    public static final IssuerInfo BBVA = new IssuerInfo("BBVA", "BBVA", "https://www.bbva.com", "+34 91 374 73 68", Countries.SPAIN);
    public static final IssuerInfo SANTANDER = new IssuerInfo("Banco Santander", "SAN", "https://www.santander.com", "+34 91 289 00 00", Countries.SPAIN);
    public static final IssuerInfo DBS = new IssuerInfo("DBS Bank", "DBS", "https://www.dbs.com.sg", "1800 111 1111", Countries.SINGAPORE);
    public static final IssuerInfo BARCLAYS = new IssuerInfo("Barclays", "BARC", "https://www.barclays.co.uk", "0800 400 100", Countries.UNITED_KINGDOM);
    public static final IssuerInfo STANDARD_CHARTERED = new IssuerInfo("Standard Chartered", "STAN", "https://www.sc.com", "+44 20 7885 8888", Countries.UNITED_KINGDOM);
    public static final IssuerInfo BOA = new IssuerInfo("Bank of America", "BOA", "https://www.bankofamerica.com", "800-432-1000", Countries.UNITED_STATES);
    public static final IssuerInfo CHASE = new IssuerInfo("Chase", "JPMC", "https://www.chase.com", "800-935-9935", Countries.UNITED_STATES);
    public static final IssuerInfo CITI = new IssuerInfo("Citibank", "CITI", "https://www.citibank.com", "800-999-9999", Countries.UNITED_STATES);
    public static final IssuerInfo UBS = new IssuerInfo("UBS", "UBS", "https://www.ubs.com", "+41 44 234 11 11", Countries.SWITZERLAND);

    public static final IssuerInfo ABC = new IssuerInfo("Agricultural Bank of China", "ABC", "https://www.abchina.com", "95599", Countries.CHINA);
    public static final IssuerInfo BOC = new IssuerInfo("Bank of China", "BOC", "https://www.boc.cn", "95566", Countries.CHINA);
    public static final IssuerInfo CCB = new IssuerInfo("China Construction Bank", "CCB", "https://www.ccb.com", "95533", Countries.CHINA);
    public static final IssuerInfo ICBC = new IssuerInfo("Industrial and Commercial Bank of China", "ICBC", "https://www.icbc.com.cn", "95588", Countries.CHINA);
    public static final IssuerInfo PSBC = new IssuerInfo("Postal Savings Bank of China", "PSBC", "https://www.psbc.com", "95580", Countries.CHINA);
    public static final IssuerInfo CEB = new IssuerInfo("China Everbright Bank", "CEB", "https://www.cebbank.com", "95595", Countries.CHINA);
    public static final IssuerInfo CMB = new IssuerInfo("China Merchants Bank", "CMB", "https://www.cmbchina.com", "95555", Countries.CHINA);
    public static final IssuerInfo CMBC = new IssuerInfo("China Minsheng Bank", "CMBC", "https://www.cmbc.com.cn", "95568", Countries.CHINA);
    public static final IssuerInfo CIB = new IssuerInfo("China Industrial Bank", "CIB", "https://www.cib.com.cn", "95561", Countries.CHINA);
    public static final IssuerInfo SPDB = new IssuerInfo("Shanghai Pudong Development Bank", "SPDB", "https://www.spdb.com.cn", "95528", Countries.CHINA);
    public static final IssuerInfo HXB = new IssuerInfo("Hua Xia Bank", "HXB", "https://www.hxb.com.cn", "95577", Countries.CHINA);
    public static final IssuerInfo BOB = new IssuerInfo("Bank of Beijing", "BOB", "https://www.bankofbeijing.com.cn", "95526", Countries.CHINA);
    public static final IssuerInfo BOS = new IssuerInfo("Bank of Shanghai", "BOS", "https://www.bankofshanghai.com", "95594", Countries.CHINA);
    public static final IssuerInfo BOCOM = new IssuerInfo("Bank of Communications", "BOCOM", "https://www.bankcomm.com", "95559", Countries.CHINA);
    public static final IssuerInfo PAB = new IssuerInfo("Ping An Bank", "PAB", "https://bank.pingan.com", "95511", Countries.CHINA);
    public static final IssuerInfo CZB = new IssuerInfo("China Zheshang Bank", "CZB", "https://www.czbank.com", "95527", Countries.CHINA);
    public static final IssuerInfo BOCD = new IssuerInfo("Bank of Chengdu", "BOCD", "https://www.bocd.com.cn", "95533", Countries.CHINA);
    public static final IssuerInfo BOL = new IssuerInfo("Bank of Luoyang", "BOL", "https://www.bankofluoyang.com", "95599", Countries.CHINA);
    public static final IssuerInfo BOCQ = new IssuerInfo("Bank of Chongqing", "BOCQ", "https://www.cqcbank.com", "966866", Countries.CHINA);
    public static final IssuerInfo BOCN = new IssuerInfo("Bank of Changsha", "BOCN", "https://www.cshbank.com", "96518", Countries.CHINA);
    public static final IssuerInfo BOCG = new IssuerInfo("Bank of Guangzhou", "BOCG", "https://www.gzcb.com.cn", "96588", Countries.CHINA);
    public static final IssuerInfo BOCS = new IssuerInfo("Bank of Suzhou", "BOCS", "https://www.suzhoubank.com", "96588", Countries.CHINA);
    public static final IssuerInfo BOCW = new IssuerInfo("Bank of Wenzhou", "BOCW", "https://www.wzbank.com.cn", "96588", Countries.CHINA);
    public static final IssuerInfo BOCX = new IssuerInfo("Bank of Xi'an", "BOCX", "https://www.xabank.com.cn", "96588", Countries.CHINA);
    public static final IssuerInfo BOCY = new IssuerInfo("Bank of Yantai", "BOCY", "https://www.yantaibank.com.cn", "96588", Countries.CHINA);
    public static final IssuerInfo BOCM = new IssuerInfo("Bank of Communications", "BOCM", "https://www.bankcomm.com", "95559", Countries.CHINA);

    static {
        // Hardcoded issuer data
        register(ANZ);
        register(NAB);
        register(ITAU);
        register(RBC);
        register(SCOTIABANK);
        register(BNP);
        register(CREDIT_AGRICOLE);
        register(SOCIETE_GENERALE);
        register(DEUTSCHE);
        register(HSBC_HK);
        register(CTBC);
        register(UNICREDIT);
        register(MUFG);
        register(ING);
        register(SBERBANK);
        register(BBVA);
        register(SANTANDER);
        register(DBS);
        register(BARCLAYS);
        register(STANDARD_CHARTERED);
        register(BOA);
        register(CHASE);
        register(CITI);
        register(UBS);
        register(ABC);
        register(BOC);
        register(CCB);
        register(ICBC);
        register(PSBC);
        register(CEB);
        register(CMB);
        register(CMBC);
        register(CIB);
        register(SPDB);
        register(HXB);
        register(BOB);
        register(BOS);
        register(BOCOM);
        register(PAB);
        register(CZB);
        register(BOL);
        register(BOCQ);
        register(BOCN);
        register(BOCM);
        register(BOCD);
        register(BOCG);
        register(BOCS);
        register(BOCW);
        register(BOCX);
        register(BOCY);
        // Add more issuers as needed
    }

    private Issuers() {}

    public static void register(IssuerInfo issuerInfo) {
        ISSUERS.putIfAbsent(issuerInfo.getIssuerShortName().toUpperCase(), issuerInfo);
    }

    public static IssuerInfo getByShortName(String shortName) {
        return ISSUERS.get(shortName.toUpperCase());
    }

    public static IssuerInfo valueOf(String shortName) {
        return getByShortName(shortName);
    }

    /**
     * Loads issuer information from a JSON string.
     * The JSON string should contain key-value pairs where the key is the issuer short name
     * and the value is an object containing issuer details.
     * Example JSON string:
     * <pre>
     * {@code
     * {
     *   "BOA": {
     *     "issuerName": "Bank of America",
     *     "issuerUrl": "https://www.bankofamerica.com",
     *     "issuerPhone": "1-800-432-1000",
     *     "issuerShortName": "BOA",
     *     "countryCode": "USA"
     *   }
     * }
     * }
     * </pre>
     *
     * @param json the JSON string containing issuer information
     */
    public static void loadIssuers(String json) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            Map<String, Map<String, String>> jsonData = mapper.readValue(json, new TypeReference<Map<String, Map<String, String>>>() {});
            jsonData.forEach((key, value) -> {
                String issuerName = value.get("issuerName");
                String issuerUrl = value.get("issuerUrl");
                String issuerPhone = value.get("issuerPhone");
                String issuerShortName = value.get("issuerShortName");
                String countryCode = value.get("countryCode");
                CountryInfo countryInfo = Countries.getByAlpha3Code(countryCode);
                IssuerInfo issuerInfo = new IssuerInfo(issuerName, issuerUrl, issuerPhone, issuerShortName, countryInfo);
                register(issuerInfo);
            });
        } catch (Exception e) {
            // Log error or handle exception
        }
    }
}